﻿// -----------------------------------------------------------------------
// <copyright file="SoundManager.cs" company="x">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace BeatEmUp
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Xna.Framework.Audio;
    using Microsoft.Xna.Framework.Input;
    using Microsoft.Xna.Framework.Media;
    using Microsoft.Xna.Framework;

    /// <summary>
    /// Sound management class
    /// </summary>
    public static class SoundManager
    {
        /// <summary>
        /// Random kill enemy sound index.
        /// </summary>
        private static Random rand;

        /// <summary>
        /// Keyboard states.
        /// </summary>
        private static KeyboardState keyboardPrevious, currentState;   

        /// <summary>
        /// Tells us whether sound is active or not.
        /// </summary>
        private static bool isSoundActive;

        /// <summary>
        /// Game manager from game class.
        /// </summary>
        private static GameManager gameManager;

        /// <summary>
        /// Menu song.
        /// </summary>
        private static Song menuMusic;

        /// <summary>
        /// Game song.
        /// </summary>
        private static Song gameMusic;

        /// <summary>
        /// Sword use sound.
        /// </summary>
        private static SoundEffect swordUseSound;

        /// <summary>
        /// Sound played after player kills an enemy.
        /// </summary>
        private static SoundEffect killEnemySound;

        /// <summary>
        /// Sound played after player is killed.
        /// </summary>
        private static SoundEffect killPlayerSound;

        /// <summary>
        /// Sound played when an enemy is injured.
        /// </summary>
        private static List<SoundEffect> enemyInjuredSound;

        /// <summary>
        /// Sound played when an player is injured.
        /// </summary>
        private static List<SoundEffect> playerInjuredSound;

        /// <summary>
        /// Sound played after player picks up an item.
        /// </summary>
        private static SoundEffect itemPickupSound;

        /// <summary>
        /// Current sound level.
        /// </summary>
        private static float soundLevel;

        public static float GetSoundLevel
        {
            get
            {
                return soundLevel;
            }
            set
            {
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="SoundManager" /> class.
        /// </summary>
        /// <param name="gameManager">Games game manager</param>
        public static void SoundManagerInitialize(GameManager gameManager)
        {
            SoundManager.gameManager = gameManager;
            SoundManager.enemyInjuredSound = new List<SoundEffect>(4);
            for (int i = 0; i < 4; i++) SoundManager.enemyInjuredSound.Add(null);
            SoundManager.playerInjuredSound = new List<SoundEffect>(4);
            for (int i = 0; i < 4; i++) SoundManager.playerInjuredSound.Add(null);
        }

        /// <summary>
        /// Gets or sets a value indicating whether sound is active.
        /// </summary>
        public static bool SetOrGetSoundActivityState
        {
            get
            {
                return SoundManager.isSoundActive;
            }

            set
            {
                SoundManager.isSoundActive = value;
            }
        }

        /// <summary>
        /// Loading sound and music contents
        /// </summary>
        internal static void LoadContent()
        {
            rand = new Random();

            SoundManager.isSoundActive = true;
            SoundManager.soundLevel = 0.5f;
            MediaPlayer.Volume = 0.5f;

            SoundManager.menuMusic = SoundManager.gameManager.Content.Load<Song>(@"Music/DST-Azimuth");
            SoundManager.gameMusic = SoundManager.gameManager.Content.Load<Song>(@"Music/DST-AngryRobotIII");
            SoundManager.swordUseSound = SoundManager.gameManager.Content.Load<SoundEffect>(@"Sounds/27858__erdie__sword04");
            SoundManager.killEnemySound = SoundManager.gameManager.Content.Load<SoundEffect>(@"Sounds/137036__pyrocamancer__beast-death");
            SoundManager.killPlayerSound = SoundManager.gameManager.Content.Load<SoundEffect>(@"Sounds/76969__michel88__paino");
            
            SoundManager.enemyInjuredSound[0] = SoundManager.gameManager.Content.Load<SoundEffect>(@"Sounds/154561__ecfike__hurt-argh-1");
            SoundManager.enemyInjuredSound[1] = SoundManager.gameManager.Content.Load<SoundEffect>(@"Sounds/hit1");
            SoundManager.enemyInjuredSound[2] = SoundManager.gameManager.Content.Load<SoundEffect>(@"Sounds/hit2");
            SoundManager.enemyInjuredSound[3] = SoundManager.gameManager.Content.Load<SoundEffect>(@"Sounds/hit3");

            SoundManager.playerInjuredSound[0] = SoundManager.gameManager.Content.Load<SoundEffect>(@"Sounds/44428__thecheeseman__hurt1");
            SoundManager.playerInjuredSound[1] = SoundManager.gameManager.Content.Load<SoundEffect>(@"Sounds/hit1");
            SoundManager.playerInjuredSound[2] = SoundManager.gameManager.Content.Load<SoundEffect>(@"Sounds/hit2");
            SoundManager.playerInjuredSound[3] = SoundManager.gameManager.Content.Load<SoundEffect>(@"Sounds/hit3");

            SoundManager.itemPickupSound = SoundManager.gameManager.Content.Load<SoundEffect>(@"Sounds/27858__erdie__sword04");

        }

        /// <summary>
        /// Starts playing menu music.
        /// </summary>
        internal static void PlayMenuMusic()
        {
            SoundManager.PlayMusic(SoundManager.menuMusic);
        }

        /// <summary>
        /// Starts playing game music.
        /// </summary>
        internal static void PlayGameMusic()
        {
            SoundManager.PlayMusic(SoundManager.gameMusic);
        }

        /// <summary>
        /// Stops playing any music.
        /// </summary>
        internal static void StopMusic()
        {
            MediaPlayer.Stop();
        }

        /// <summary>
        /// Plays sword use sound.
        /// </summary>
        internal static void PlayerSwordUseSound()
        {
            SoundManager.PlaySound(SoundManager.swordUseSound);
        }

        /// <summary>
        /// Plays kill enemy sound.
        /// </summary>
        internal static void KillEnemySound()
        {
            SoundManager.PlaySound(SoundManager.killEnemySound);
        }

        /// <summary>
        /// Plays kill player sound.
        /// </summary>
        internal static void KillPlayerSound()
        {
            SoundManager.PlaySound(SoundManager.killPlayerSound);
        }

        /// <summary>
        /// Plays player injured use sound.
        /// </summary>
        internal static void PlayerInjuredSound()
        {
            int soundIndex = rand.Next(0, 3);
            SoundManager.PlaySound(SoundManager.playerInjuredSound[soundIndex]);
        }

        /// <summary>
        /// Plays enemy injured sound.
        /// </summary>
        internal static void EnemyInjuredSound()
        {
            int soundIndex = rand.Next(0, 3);
            SoundManager.PlaySound(SoundManager.enemyInjuredSound[soundIndex]);
        }

        /// <summary>
        /// Plays item pickup sound.
        /// </summary>
        internal static void ItemPickupSound()
        {
            SoundManager.PlaySound(SoundManager.itemPickupSound);
        }

        /// <summary>
        /// Enables or disables sound effects.
        /// </summary>
        /// <param name="soundActive">Should sound be active or not.</param>
        internal static void EnableSound(bool soundActive)
        {
            SoundManager.SetOrGetSoundActivityState = soundActive;
        }

        /// <summary>
        /// Enables or disables music.
        /// </summary>
        /// <param name="musicActive">Should music be active or not.</param>
        internal static void EnableMusic(bool musicActive)
        {
            MediaPlayer.IsMuted = musicActive;
        }

        /// <summary>
        /// Increases sound level.
        /// </summary>
        internal static void IncreaseSoundLevel()
        {
            SoundManager.soundLevel += 0.1f;
            if (SoundManager.soundLevel >= 1.0f)
            {
                SoundManager.soundLevel = 1.0f;
            }
        }

        /// <summary>
        /// Decreases sound level.
        /// </summary>
        internal static void DecreaseSoundLevel()
        {
            SoundManager.soundLevel -= 0.1f;
            if (SoundManager.soundLevel <= 0.1f)
            {
                SoundManager.soundLevel = 0.0f;             
            }
        }

        /// <summary>
        /// Increases music level.
        /// </summary>
        internal static void IncreaseMusicLevel()
        {
            MediaPlayer.Volume += 0.1f;
            if (MediaPlayer.Volume >= 1.0f)
            {
                MediaPlayer.Volume = 1.0f;               
            }
        }

        /// <summary>
        /// Decreases music level.
        /// </summary>
        
        internal static void DecreaseMusicLevel()
        {
            MediaPlayer.Volume -= 0.1f;
            if (MediaPlayer.Volume <= 0.1f)
            {
                MediaPlayer.Volume = 0.0f;
            }
        }

        /// <summary>
        /// Sound manager key handling function
        /// </summary>
        internal static void Update()
        {
            SoundManager.currentState = Keyboard.GetState();

            if (SoundManager.currentState.IsKeyDown(Keys.Add) && SoundManager.currentState != SoundManager.keyboardPrevious)
            {
                SoundManager.IncreaseMusicLevel();
            }

            if (SoundManager.currentState.IsKeyDown(Keys.Subtract) && SoundManager.currentState != SoundManager.keyboardPrevious)
            {
                SoundManager.DecreaseMusicLevel();
            }

            if (SoundManager.currentState.IsKeyDown(Keys.PageUp) && SoundManager.currentState != SoundManager.keyboardPrevious)
            {
                SoundManager.IncreaseSoundLevel();
            }

            if (SoundManager.currentState.IsKeyDown(Keys.PageDown) && SoundManager.currentState != SoundManager.keyboardPrevious)
            {
                SoundManager.DecreaseSoundLevel();
            }

            SoundManager.keyboardPrevious = SoundManager.currentState;
        }

        /// <summary>
        /// Volume level to string parser.
        /// </summary>
        /// <returns>Returns music and sound volume as formatted string.</returns>
        internal static string ReturnMusicAndSoundVolume()
        {
            float sv;
            float mv;

            mv = MediaPlayer.Volume;
            mv = (float)Math.Round(mv, 1);

            sv = SoundManager.soundLevel;
            sv = (float)Math.Round(sv, 1);

            return "|Sound volume: " + string.Format("{0}%",sv*100)
                +
                "|\n|Music volume: " + string.Format("{0}%",mv*100)
                + 
                "|\n|Press - or + to adjust music volume.|" + "\n|Press PgUp or PgDown to adjust sound volume|";
        }

        /// <summary>
        /// Starts playing music.
        /// </summary>
        /// <param name="song">Music to play.</param>
        private static void PlayMusic(Song song)
        {
            MediaPlayer.Play(song);
        }

        /// <summary>
        /// Plays given sound
        /// </summary>
        /// <param name="soundEffect">Sound to play.</param>
        private static void PlaySound(SoundEffect soundEffect)
        {
            if (SoundManager.SetOrGetSoundActivityState)
            {
                soundEffect.Play(SoundManager.soundLevel, 0.0f, 0.0f);
            }
        }
    }
}
